package cn.larry.common.annotation;

import cn.larry.common.exception.Wechath5TokenException;
import cn.larry.common.exception.Wechath5handlersException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.text.WordUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * larry
 * 2022/12/26 22:20
 *
 * @Version 1.0
 */
@Slf4j
@Aspect
@Component
public class Wechath5CheckAop {

    @Resource
    Map<String, Wechath5Checker> checkerMap;

    @Around("@annotation(checkListAnno)")
    public Object check(final ProceedingJoinPoint joinPoint, Wechath5CheckListAnno checkListAnno) throws Throwable {

//        String className = joinPoint.getSignature().getName();
        final Object[] args = joinPoint.getArgs();

        Object requestParam = null;// 责任链路最终请求入参
        Object reponseParam = null;// 责任链路最终响应出参

        // 校验参数
        if (args == null || args.length < 1 || args[0] == null) {
            log.error("request parameter is null");
        } else {
            requestParam = args[0];
        }

        String methodName = getMethod(joinPoint).getName();

        try {
            final Wechath5CheckAnno[] checkAnnos = checkListAnno.checkAnnos();
            for (Wechath5CheckAnno checkAnno : checkAnnos) {
                final String checkerName = WordUtils.uncapitalize(checkAnno.checkerClass().getSimpleName());
                final Wechath5Checker checker = checkerMap.get(checkerName);

                if (checkAnno.isAround())// 是否环绕前置切面
                    requestParam = checker.aroundBefore(requestParam);

                requestParam = checker.check(requestParam, methodName);

            }

            long startTime = System.currentTimeMillis();
            reponseParam = joinPoint.proceed(args);
//            log.info("耗时：{}", System.currentTimeMillis() - startTime);
            log.info("请求接口：{}，耗时：{} ms", methodName, System.currentTimeMillis() - startTime);

            for (Wechath5CheckAnno checkAnno : checkAnnos) {
                final String checkerName = WordUtils.uncapitalize(checkAnno.checkerClass().getSimpleName());
                final Wechath5Checker checker = checkerMap.get(checkerName);
                if (checkAnno.isAround()) {
                    reponseParam = checker.aroundAfter(requestParam, reponseParam);
                }
            }
        } catch (Throwable throwable) {
            if (throwable instanceof Wechath5handlersException)
                throw new Wechath5handlersException(throwable.getMessage());
            else if (throwable instanceof Wechath5TokenException) {
                throw new Wechath5TokenException(throwable.getMessage());
            }else if (throwable instanceof RuntimeException){
                throw new Wechath5handlersException(throwable.getMessage());
            }else{
                log.error("系统异常", throwable);
                throw new Wechath5handlersException("系统异常");
            }
        }
        return reponseParam;
    }

    /**
     * 获取拦截方法信息
     *
     * @param joinPoint
     * @return
     */
    private static Method getMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        return methodSignature.getMethod();
    }

}
